<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      class EventEmitter {
        constructor() {
          this._events = {};
        }
        // 考虑once属性
        // listener:{
        //   listener:fn;
        //   once:false
        // }
        on(eventName, listener) {
          // 获取对应事件绑定的回调函数
          let task = this._events[evevntName] || [];

          // 判断
          let isWrap = typeof listener == "object";
          if (!task.includes(listener)) {
            task.push(isWrap ? listener : { listener: listener, once: false });
          }
        }
        off(eventName, listener) {
          let task = this._events[eventName];
          if (task.includes(listener)) {
            let idx = task.indexOf(listener);
            task.splice(idx, 1);
          }
        }

        once(eventName, listener) {
          this.on(eventName, { listener: listener, once: true });
        }
        emit(eventName, data) {
          let task = this._events[eventName];
          if (!task) {
            return;
          }
          for (let i = 0; i < task.length; i++) {
            let listener = task[i];
            listener.listener.apply(this, data || []);
            if (listener.once) {
              this.off(eventName, listener);
            }
          }
        }
      }
    </script>
  </body>
</html>
